﻿#pragma once
#ifndef Client_hpp
#define Client_hpp


#include<string>
#include<atomic>
#include<boost/asio.hpp>
#include"NetworkDef.hpp"

namespace MMFNetwork
{

    using namespace boost::asio;

    //回调函数类型
    using ClientErrorHandler = std::function<void(boost::system::error_code err)>;        ///< 错误处理回调函数类型
    using ClientStatusHandler = std::function<void(Status status)>;                       ///< 状态处理回调函数类型
    using ClientAsyncHandler = std::function<void(void* buffer, bool state)>;             ///< 异步收发回调函数类型
    using ClientPackageHandler = std::function<void(void* pkg, size_t size)>;             ///< 数据包处理回调函数类型

    class Client
    {

        io_context mService;                ///< asio上下文，需要在异步线程中运行
        ip::tcp::socket mSocket;            ///< 套接字
        std::string mLocalIp;               ///< 本地ip
        std::string mRemoteIp;              ///< 远端ip        
        uint16_t mRemotePort;               ///< 远端端口
        uint16_t mLocalPort;                ///< 本地端口
        bool mIsSym;                        ///< 同步模式，不启用自动接收包

        const uint32_t mBufferSize;             ///< 用于接收的缓存大小
        std::vector<void*> mRecvBuffers;        ///< 接收缓存，小黄缓冲一个用于接收，一个用于处理数据
        uint8_t mCurrentBuff;                   ///< 当前使用的是第几块buff，块数只能为2
        uint32_t mCurrentRecvBytes;             ///< 当前接收的字节数

        Status mStatus;                     ///< 状态
        MMFInetFamily mFamily;              ///< 因特网类型

        ClientErrorHandler mErrHandler;         ///< 错误处理回调函数
        ClientStatusHandler mStatusHandler;     ///< 状态处理回调函数
        ClientAsyncHandler mAsyncHandler;       ///< 异步收发回调函数
        ClientPackageHandler mPkgHandler;       ///< 数据包处理回调函数

        std::shared_ptr<std::thread> mWorker;   ///< 子线程用于运行io_context
        std::atomic<bool> mIsStop;              ///< 是否退出

    public:

        Client(
            const std::string& remoteIp,
            uint16_t remotePort,
            uint32_t bufferSize,
            ClientErrorHandler errHandler,
            ClientStatusHandler statusHandler,
            ClientAsyncHandler asyncHandler,
            ClientPackageHandler pkgHandler,
            MMFInetFamily family,
            bool Sym = false
        );

        ~Client();

        bool Start();
        void Stop();

        const std::string& LocalIp();
        const std::string& RemoteIp();

        uint16_t LocalPort();
        uint16_t RemotePort();

        Status CurrentStatus();

        bool Send(void* buff, uint32_t count);
        bool Recv(void* buff, uint32_t count);

        //发送数据的时候是确定的知道数据要发送多少的
        //可以直接通过回调知道发送完毕即可，甚至不出错的情况下，都不需要知道结果
        void AsyncSend(void* buff, uint32_t count);

        //接收预定字节数的数据，
        //除非明确知道数据大小
        void AsyncRecv(void* buff, uint32_t count, const ClientAsyncHandler& handler);

        //接收数据包
        //通过数据包通过回调进行通知
        //收完一个数据包会继续收下一个数据包
        void AsyncRecvPackage();
    };
}



#endif